package com.jnchen.jwt.impl;

import com.jnchen.jwt.api.JwtInterface;
import com.jnchen.jwt.entity.User;
import com.jnchen.jwt.util.RsaUtil;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
import java.util.Date;

/**
 * nimbus-jose-jwt
 *
 * @author jnchen
 * @date 2020/10/30 10:13
 */
public class NimbusJoseJwtImpl implements JwtInterface {

    private static final JWSSigner JWS_SIGNER;
    private static final JWSVerifier JWS_VERIFIER;

    static {
        KeyPair pair = RsaUtil.getRsaKey();
        JWS_SIGNER = new RSASSASigner(pair.getPrivate());
        JWS_VERIFIER = new RSASSAVerifier((RSAPublicKey) pair.getPublic());
    }

    @Override
    public String createJwt(User user, long expireIn) {
        try {
            JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                    .claim("id", user.getId())
                    .claim("name", user.getName())
                    .claim("operations", user.getOperations())
                    .expirationTime(new Date(System.currentTimeMillis() + expireIn)).build();
            JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS512).build();
            SignedJWT signedjwt = new SignedJWT(header, claimsSet);
            signedjwt.sign(JWS_SIGNER);
            return signedjwt.serialize();
        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public User parseJwt(String token) {
        try {
            SignedJWT signedjwt = SignedJWT.parse(token);
            signedjwt.verify(JWS_VERIFIER);
            JWTClaimsSet jwtClaimsSet = signedjwt.getJWTClaimsSet();
            User user = new User();
            user.setId(jwtClaimsSet.getIntegerClaim("id"));
            user.setName(jwtClaimsSet.getStringClaim("name"));
            user.setOperations(jwtClaimsSet.getStringListClaim("operations"));
            return user;
        } catch (ParseException | JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean checkJwt(String token) {
        try {
            SignedJWT signedjwt = SignedJWT.parse(token);
            return signedjwt.verify(JWS_VERIFIER);
        } catch (ParseException | JOSEException e) {
            e.printStackTrace();
        }
        return false;
    }
}
